#include <ESP8266WiFi.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include <string>  
#include <ArduinoJson.h>
 
int Led= 4;
// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "ESP8266WiFi";
const char* mqttServer = "192.168.103.55";
 
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
 
void setup() {
  Serial.begin(9600);
  WiFiManager wifiManager;
  Serial.println("自动配网..");
  wifiManager.autoConnect(ssid);
  //4号引脚输出模式
  pinMode(Led, OUTPUT);
  // 设置MQTT服务器和端口号
  mqttClient.setServer(mqttServer, 1883);
  mqttClient.setCallback(receiveCallback);
  // 连接MQTT服务器
  connectMQTTServer();
}
 
void loop() { 
  if (mqttClient.connected()) { // 如果开发板成功连接服务器    
    mqttClient.loop();          // 保持客户端心跳
  } else {                  // 如果开发板未能成功连接服务器
    connectMQTTServer();    // 则尝试连接服务器
  }
}

StaticJsonDocument<200> jsonBuffer; //声明一个JsonDocument对象，长度200
//接收到消息样例{"body":{"status":1}}
 // 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  String str= "";
  for (int i = 0; i < length; i++) {
   str+=(char)payload[i];
  }
  Serial.print(str);
  // 反序列化JSON
    DeserializationError error = deserializeJson(jsonBuffer, str);
    if (error) 
    {
        Serial.print("反序列化json失败");
        Serial.println(error.f_str());
        return;
    }
    // 解析JSON
    long status = jsonBuffer["body"]["status"];       // 读取整形数据
    //const char* = jsonBuffer["body"]["status"];  
  if (status== 1) {     // 如果收到的信息以“1”为开始
    digitalWrite(Led, LOW);  // 则点亮LED。
  } else if(status== 0){                           
    digitalWrite(Led, HIGH); // 否则熄灭LED。
  }
} 
 // 订阅指定主题
void subscribeTopic(){
  
  String topicString = "mainled";
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str()); 
  // 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
  if(mqttClient.subscribe(subTopic)){
    Serial.println("订阅主题:");
    Serial.println(subTopic);
   
  } else {
    Serial.print("订阅失败");
  }  
} 

void connectMQTTServer(){
  // 根据ESP8266的MAC地址生成客户端ID（避免与其它ESP8266的客户端ID重名）
  String clientId = "esp8266-" + WiFi.macAddress();
  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) { 
    Serial.println("MQTT 服务器连接成功.");
    Serial.println("服务器地址: ");
    Serial.println(mqttServer);
    Serial.println("客户端id:");
    Serial.println(clientId);
    subscribeTopic();
  } else {
    Serial.print("MQTT 服务器连接失败. 状态码:");
    Serial.println(mqttClient.state());
    delay(3000);
  }   
}